/* * * Copyright (C) 2012-2014 R T Huitema. All Rights Reserved. * Web: www.42.co.nz * Email: robert@42.co.nz * Author: R T Huitema * * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ package nz.co.fortytwo.signalk.server; import static nz.co.fortytwo.signalk.util.SignalKConstants.SIGNALK_AUTH; import static nz.co.fortytwo.signalk.util.SignalKConstants.SIGNALK_DISCOVERY; import static nz.co.fortytwo.signalk.util.SignalKConstants.SIGNALK_WS; import static nz.co.fortytwo.signalk.util.SignalKConstants.websocketUrl; import java.io.File; import java.io.IOException; import java.util.ArrayList; import java.util.List; import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; import mjson.Json; import nz.co.fortytwo.signalk.util.SignalKConstants; import org.apache.camel.Produce; import org.apache.camel.ProducerTemplate; import org.apache.camel.builder.RouteBuilder; import org.apache.commons.io.FileUtils; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.junit.Test; import com.ning.http.client.AsyncHttpClient; import com.ning.http.client.Response; import com.ning.http.client.websocket.DefaultWebSocketListener; import com.ning.http.client.websocket.WebSocket; import com.ning.http.client.websocket.WebSocketTextListener; import com.ning.http.client.websocket.WebSocketUpgradeHandler; public class SubcribeWsTest extends SignalKCamelTestSupport{ private static Logger logger = LogManager.getLogger(SubcribeWsTest.class); String jsonDiff = null; @Produce(uri = "direct:input") protected ProducerTemplate template; public SubcribeWsTest(){ try { jsonDiff = FileUtils.readFileToString(new File("src/test/resources/samples/testUpdate.json")); jsonDiff=jsonDiff.replaceAll("self", SignalKConstants.self); } catch (IOException e) { logger.error(e); fail(); } } @Test public void shouldGetWsUrl() throws Exception { final AsyncHttpClient c = new AsyncHttpClient(); //get a sessionid Response r1 = c.prepareGet("http://localhost:"+restPort+SIGNALK_AUTH+"/demo/pass").execute().get(); assertEquals(200, r1.getStatusCode()); Response r2 = c.prepareGet("http://localhost:"+restPort+SIGNALK_DISCOVERY).setCookies(r1.getCookies()).execute().get(); Json json = Json.read(r2.getResponseBody()); assertEquals("ws://localhost:"+wsPort+SIGNALK_WS, json.at("endpoints").at("v1").at(websocketUrl).asString()); c.close(); } @Test public void shouldGetSubscribeWsResponse() throws Exception { final List<String> received = new ArrayList<String>(); final CountDownLatch latch2 = new CountDownLatch(1); final CountDownLatch latch3 = new CountDownLatch(5); final CountDownLatch latch4 = new CountDownLatch(1); final AsyncHttpClient c = new AsyncHttpClient(); template.sendBody(RouteManager.SEDA_INPUT,jsonDiff); //get a sessionid Response r1 = c.prepareGet("http://localhost:"+restPort+SIGNALK_AUTH+"/demo/pass").execute().get(); Response r2 = c.prepareGet("http://localhost:"+restPort+SIGNALK_DISCOVERY).setCookies(r1.getCookies()).execute().get(); Json json = Json.read(r2.getResponseBody()); logger.debug(json); latch2.await(3, TimeUnit.SECONDS); //await messages String restUrl = json.at("endpoints").at("v1").at(websocketUrl).asString(); logger.debug("Open websocket at: "+restUrl); WebSocket websocket = c.prepareGet(restUrl).setCookies(r1.getCookies()).execute( new WebSocketUpgradeHandler.Builder() .addWebSocketListener(new DefaultWebSocketListener() { @Override public void onMessage(String message) { logger.info("received --> " + message); //{"context":"vessels.self","updates":[]} if(message.startsWith("{\"context\":\"vessels.self\",\"updates\":[]}"))return;//heartbeats if(message.startsWith("{\"self\":\"motu\",\"version\""))return;//heartbeats received.add(message); latch3.countDown(); } @Override public void onFragment(String fragment, boolean last) { logger.info("fragment --> " + fragment); if(fragment.startsWith("{\"context\":\"vessels.self\",\"updates\":[]}"))return;//heartbeats if(fragment.startsWith("{\"self\":\"motu\",\"version\""))return;//heartbeats received.add(fragment); latch3.countDown(); } }).build()).get(); //subscribe String subscribeMsg="{\"context\":\"vessels.motu\",\"subscribe\":[{\"path\":\"navigation\"}]}"; websocket.sendTextMessage(subscribeMsg); logger.debug("Sent subscribe = "+subscribeMsg); latch4.await(2, TimeUnit.SECONDS); websocket.sendTextMessage(jsonDiff); logger.debug("Sent update = "+jsonDiff); latch3.await(10, TimeUnit.SECONDS); //assertTrue(latch3.await(15, TimeUnit.SECONDS)); String fullMsg = null; for(String msg : received){ logger.debug("Received msg = "+msg); if(msg.contains("\"updates\":[{\"")&&msg.contains("\"path\":\"navigation")){ fullMsg=msg; } } assertTrue(received.size()>1); //Json sk = Json.read("{\"context\":\"vessels."+SignalKConstants.self+".navigation\",\"updates\":[{\"values\":[{\"path\":\"courseOverGroundTrue\",\"value\":3.0176},{\"path\":\"speedOverGround\",\"value\":3.85}],\"source\":{\"timestamp\":\"2014-08-15T16:00:00.081+00:00\",\"device\":\"/dev/actisense\",\"src\":\"115\",\"pgn\":\"128267\"}}]}"); //Json sk = Json.read("{\"context\":\"vessels.motu\",\"updates\":[{\"values\":[{\"path\":\"navigation.courseOverGroundTrue\",\"value\":3.0176},{\"path\":\"navigation.speedOverGround\",\"value\":3.85}],\"timestamp\":\"2014-08-15T16:00:00.081+00:00\",\"source\":{\"device\":\"/dev/actisense\",\"src\":\"115\",\"pgn\":\"128267\"}}]}"); assertNotNull(fullMsg); assertTrue(fullMsg.contains("\"context\":\"vessels.motu\"")); assertTrue(fullMsg.contains("\"path\":\"navigation.courseOverGroundTrue\"")); assertTrue(fullMsg.contains("\"value\":3.0176")); assertTrue(fullMsg.contains("\"updates\":[{")); c.close(); } @Override public void configureRouteBuilder(RouteBuilder routeBuilder) { // TODO Auto-generated method stub try { ((RouteManager)routeBuilder).configure0(); } catch (Exception e) { // TODO Auto-generated catch block logger.error(e); fail(); } } }